home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / os2 / mpegenc / src / postdct.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-01  |  10.9 KB  |  489 lines

  1. /*===========================================================================*
  2.  * postdct.c                                     *
  3.  *                                         *
  4.  *    Procedures concerned with MPEG post-DCT processing:             *
  5.  *        quantization and RLE Huffman encoding                 *
  6.  *                                         *
  7.  * EXPORTED PROCEDURES:                                 *
  8.  *    Mpost_QuantZigBlock                             *
  9.  *    Mpost_RLEHuffIBlock                             *
  10.  *    Mpost_RLEHuffPBlock                             *
  11.  *    Mpost_UnQuantZigBlock                             *
  12.  *                                         *
  13.  *===========================================================================*/
  14.  
  15. /*
  16.  * Copyright (c) 1993 The Regents of the University of California.
  17.  * All rights reserved.
  18.  *
  19.  * Permission to use, copy, modify, and distribute this software and its
  20.  * documentation for any purpose, without fee, and without written agreement is
  21.  * hereby granted, provided that the above copyright notice and the following
  22.  * two paragraphs appear in all copies of this software.
  23.  *
  24.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  25.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  26.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  27.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  *
  29.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  30.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  31.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  32.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  33.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  34.  */
  35.  
  36. /*
  37.  *  $Header: /n/picasso/users/keving/encode/src/RCS/postdct.c,v 1.11 1993/07/22 22:23:43 keving Exp keving $
  38.  *  $Log: postdct.c,v $
  39.  * Revision 1.11  1993/07/22  22:23:43  keving
  40.  * nothing
  41.  *
  42.  * Revision 1.10  1993/06/30  20:06:09  keving
  43.  * nothing
  44.  *
  45.  * Revision 1.9  1993/06/03  21:08:08  keving
  46.  * nothing
  47.  *
  48.  * Revision 1.8  1993/02/24  18:57:19  keving
  49.  * nothing
  50.  *
  51.  * Revision 1.7  1993/02/23  22:58:36  keving
  52.  * nothing
  53.  *
  54.  * Revision 1.6  1993/02/23  22:54:56  keving
  55.  * nothing
  56.  *
  57.  * Revision 1.5  1993/02/17  23:18:20  dwallach
  58.  * checkin prior to keving's joining the project
  59.  *
  60.  * Revision 1.4  1993/01/18  10:20:02  dwallach
  61.  * *** empty log message ***
  62.  *
  63.  * Revision 1.3  1993/01/18  10:17:29  dwallach
  64.  * RCS headers installed, code indented uniformly
  65.  *
  66.  * Revision 1.3  1993/01/18  10:17:29  dwallach
  67.  * RCS headers installed, code indented uniformly
  68.  *
  69.  */
  70.  
  71.  
  72. /*==============*
  73.  * HEADER FILES *
  74.  *==============*/
  75.  
  76. #include <assert.h>
  77. #include "all.h"
  78. #include "mtypes.h"
  79. #include "bitio.h"
  80. #include "huff.h"
  81. #include "postdct.h"
  82.  
  83.  
  84. /*==================*
  85.  * STATIC VARIABLES *
  86.  *==================*/
  87.  
  88. /* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
  89. static int ZAG[] = {
  90.     0, 1, 8, 16, 9, 2, 3, 10,
  91.     17, 24, 32, 25, 18, 11, 4, 5,
  92.     12, 19, 26, 33, 40, 48, 41, 34,
  93.     27, 20, 13, 6, 7, 14, 21, 28,
  94.     35, 42, 49, 56, 57, 50, 43, 36,
  95.     29, 22, 15, 23, 30, 37, 44, 51,
  96.     58, 59, 52, 45, 38, 31, 39, 46,
  97.     53, 60, 61, 54, 47, 55, 62, 63
  98. };
  99.  
  100.  
  101. /*
  102.  * possible optimization: reorder the qtable in the correct zigzag order, to
  103.  * reduce the number of necessary lookups
  104.  *
  105.  * this table comes from the MPEG draft, p. D-16, Fig. 2-D.15.
  106.  */
  107. static int qtable[] = {
  108.     8, 16, 19, 22, 26, 27, 29, 34,
  109.     16, 16, 22, 24, 27, 29, 34, 37,
  110.     19, 22, 26, 27, 29, 34, 34, 38,
  111.     22, 22, 26, 27, 29, 34, 37, 40,
  112.     22, 26, 27, 29, 32, 35, 40, 48,
  113.     26, 27, 29, 32, 35, 40, 48, 58,
  114.     26, 27, 29, 34, 38, 46, 56, 69,
  115.     27, 29, 35, 38, 46, 56, 69, 83
  116. };
  117.  
  118.  
  119. /*=====================*
  120.  * EXPORTED PROCEDURES *
  121.  *=====================*/
  122.  
  123. /*===========================================================================*
  124.  *
  125.  * Mpost_UnQuantZigBlock
  126.  *
  127.  *    unquantize and zig-zag (decode) a single block
  128.  *
  129.  * RETURNS:    nothing
  130.  *
  131.  * SIDE EFFECTS:    none
  132.  *
  133.  *===========================================================================*/
  134. void
  135. Mpost_UnQuantZigBlock(in, out, qscale, iblock)
  136.     FlatBlock in;
  137.     Block out;
  138.     int qscale;
  139.     boolean iblock;
  140. {
  141.     register int index;
  142.     int        start;
  143.     int        position;
  144.     register int        qentry;
  145.     int        level, coeff;
  146.  
  147.     if ( iblock ) {
  148.     ((int16 *)out)[0] = (int16)(in[0]*qtable[0]);
  149.  
  150.     start = 1;
  151.     } else {
  152.     start = 0;
  153.     }
  154.  
  155.     for ( index = start; index < DCTSIZE_SQ; index++ ) {
  156.     position = ZAG[index];
  157.  
  158.     if (iblock) {
  159.         qentry = qtable[position] * qscale;
  160.     } else {
  161.         qentry = 16 * qscale;
  162.     }
  163.  
  164.     level = in[index];
  165.  
  166.     if ( iblock ) {
  167.         coeff = (2*level*qentry) >> 4;
  168.         if ( (coeff & 1) == 0 ) {
  169.         if ( coeff < 0 ) {
  170.             coeff++;
  171.         } else if ( coeff > 0 ) {
  172.             coeff--;
  173.         }
  174.         }
  175.  
  176.         if ( coeff > 2047 ) {
  177.         coeff = 2047;
  178.         } else if ( coeff < -2048 ) {
  179.         coeff = -2048;
  180.         }
  181.     } else {
  182.         if ( level == 0 ) {
  183.         coeff = 0;
  184.         } else if ( level < 0 ) {
  185.         coeff = (((2*level)-1)*qentry) >> 4;
  186.         if ( (coeff & 1) == 0 ) {
  187.             coeff++;
  188.         }
  189.         } else {
  190.         coeff = (((2*level)+1)*qentry) >> 4;
  191.         if ( (coeff & 1) == 0 ) {
  192.             coeff--;
  193.         }
  194.         }
  195.  
  196.         if ( coeff > 2047 ) {
  197.         coeff = 2047;
  198.         } else if ( coeff < -2048 ) {
  199.         coeff = -2048;
  200.         }
  201.     }
  202.  
  203.     ((int16 *)out)[position] = coeff;
  204.     }
  205. }
  206.  
  207.  
  208. /*===========================================================================*
  209.  *
  210.  * Mpost_QuantZigBlock
  211.  *
  212.  *    quantize and zigzags a block
  213.  *
  214.  * RETURNS:    TRUE iff resulting output is non-zero, FALSE if all zero
  215.  *
  216.  * SIDE EFFECTS:    none
  217.  *
  218.  *===========================================================================*/
  219. boolean
  220. Mpost_QuantZigBlock(in, out, qscale, iblock)
  221.     Block in;
  222.     FlatBlock out;
  223.     register int qscale;
  224.     int iblock;
  225. {
  226.     register int i;
  227.     register int16 temp;
  228.     register int qentry;
  229.     register int position;
  230.     boolean nonZero = FALSE;
  231.  
  232.     DBG_PRINT(("Mpost_QuantZigBlock...\n"));
  233.     if (iblock) {
  234.     /*
  235.      * the DC coefficient is handled specially -- it's not
  236.      * sensitive to qscale, but everything else is
  237.      */
  238.     temp = ((int16 *) in)[ZAG[0]];
  239.     qentry = qtable[ZAG[0]];
  240.  
  241.         if (temp < 0) {
  242.             temp = -temp;
  243.             temp += qentry >> 1;
  244.             temp /= qentry;
  245.             temp = -temp;
  246.     } else {
  247.             temp += qentry >> 1;
  248.             temp /= qentry;
  249.     }
  250.     if ( temp != 0 ) {
  251.         nonZero = TRUE;
  252.     }
  253.     out[0] = temp;
  254.  
  255.     for (i = 1; i < DCTSIZE_SQ; i++) {
  256.         position = ZAG[i];
  257.         temp = ((int16 *) in)[position];
  258.  
  259.         qentry = qtable[position] * qscale;
  260.  
  261.         /* see 1993 MPEG doc, section D.6.3.4 */
  262.         if (temp < 0) {
  263.         temp = -temp;
  264.         temp = (temp << 3);
  265.         temp += (qentry >> 1);
  266.         temp /= qentry;
  267.         temp = -temp;
  268.         } else {
  269.         temp = (temp << 3);
  270.         temp += (qentry >> 1);
  271.         temp /= qentry;
  272.         }
  273.  
  274.         if ( temp != 0 ) {
  275.         nonZero = TRUE;
  276.         }
  277.         out[i] = temp;
  278.     }
  279.     } else {
  280.     for (i = 0; i < DCTSIZE_SQ; i++) {
  281.         position = ZAG[i];
  282.         temp = ((int16 *) in)[position];
  283.  
  284.         /* multiply by 16 */
  285.         qentry = qscale << 4;
  286.  
  287.         /* see 1993 MPEG doc, D.6.4.5 */
  288.         temp = (temp << 3);
  289.         temp /= qentry;
  290.  
  291.         if ( temp != 0 ) {
  292.         nonZero = TRUE;
  293.         }
  294.         out[i] = temp;
  295.     }
  296.     }
  297.  
  298.     return nonZero;
  299. }
  300.  
  301.  
  302.  
  303. /*===========================================================================*
  304.  *
  305.  * Mpost_RLEHuffIBlock
  306.  *
  307.  *    generate the huffman bits from an I-block
  308.  *
  309.  * RETURNS:    nothing
  310.  *
  311.  * SIDE EFFECTS:    none
  312.  *
  313.  *===========================================================================*/
  314. void
  315. Mpost_RLEHuffIBlock(in, out)
  316.     FlatBlock in;
  317.     BitBucket *out;
  318. {
  319.     register int i;
  320.     register int nzeros = 0;
  321.     register int16 cur;
  322.     register int16 acur;
  323.     register uint32 code;
  324.     register int nbits;
  325.  
  326.     /*
  327.      * yes, Virginia, we start at 1.  The DC coefficient is handled
  328.      * specially, elsewhere.  Not here.
  329.      */
  330.     for (i = 1; i < DCTSIZE_SQ; i++) {
  331.     cur = in[i];
  332.     acur = ABS(cur);
  333.     if (cur) {
  334.         if ( (nzeros < HUFF_MAXRUN) && (acur < huff_maxlevel[nzeros])) {
  335.             /*
  336.          * encode using the Huffman tables
  337.          */
  338.  
  339.         code = (huff_table[nzeros])[acur];
  340.         nbits = (huff_bits[nzeros])[acur];
  341.  
  342.         if (cur < 0) {
  343.             code |= 1;    /* the sign bit */
  344.         }
  345.         Bitio_Write(out, code, nbits);
  346.         } else {
  347.         /*
  348.          * encode using the escape code
  349.          */
  350.         Bitio_Write(out, 0x1, 6);    /* ESCAPE */
  351.         Bitio_Write(out, nzeros, 6);    /* Run-Length */
  352.  
  353.         /*
  354.              * this shouldn't happen, but the other
  355.              * choice is to bomb out and dump core...
  356.              */
  357.         if (cur < -255) {
  358.             cur = -255;
  359.         } else if (cur > 255) {
  360.             cur = 255;
  361.         }
  362.  
  363.         DBG_PRINT(("Level\n"));
  364.         if (acur < 128) {
  365.             Bitio_Write(out, cur, 8);
  366.         } else {
  367.             if (cur < 0) {
  368.             Bitio_Write(out, 0x8001 + cur + 255, 16);
  369.             } else {
  370.             Bitio_Write(out, cur, 16);
  371.             }
  372.         }
  373.         }
  374.         nzeros = 0;
  375.     } else {
  376.         nzeros++;
  377.     }
  378.     }
  379.     DBG_PRINT(("End of block\n"));
  380.     Bitio_Write(out, 0x2, 2);    /* end of block marker */
  381. }
  382.  
  383.  
  384. /*===========================================================================*
  385.  *
  386.  * Mpost_RLEHuffPBlock
  387.  *
  388.  *    generate the huffman bits from an P-block
  389.  *
  390.  * RETURNS:    nothing
  391.  *
  392.  * SIDE EFFECTS:    none
  393.  *
  394.  *===========================================================================*/
  395. void
  396. Mpost_RLEHuffPBlock(in, out)
  397.     FlatBlock in;
  398.     BitBucket *out;
  399. {
  400.     register int i;
  401.     register int nzeros = 0;
  402.     register int16 cur;
  403.     register int16 acur;
  404.     register uint32 code;
  405.     register int nbits;
  406.     boolean first_dct = TRUE;
  407.  
  408.     /*
  409.      * yes, Virginia, we start at 0.
  410.      */
  411.     for (i = 0; i < DCTSIZE_SQ; i++) {
  412.     cur = in[i];
  413.     acur = ABS(cur);
  414.     if (cur) {
  415.         if (nzeros < HUFF_MAXRUN && acur < huff_maxlevel[nzeros]) {
  416.             /*
  417.          * encode using the Huffman tables
  418.          */
  419.  
  420.         DBG_PRINT(("rle_huff %02d: Run %02d, Level %02d\n", i, nzeros, cur));
  421.         assert(cur);
  422.  
  423.         if ( first_dct && (nzeros == 0) && (acur == 1) ) {
  424.             /* actually, only needs = 0x2 */
  425.             code = (cur == 1) ? 0x2 : 0x3;
  426.             nbits = 2;
  427.         } else {
  428.             code = (huff_table[nzeros])[acur];
  429.             nbits = (huff_bits[nzeros])[acur];
  430.         }
  431.  
  432.         assert(nbits);
  433.  
  434.         if (cur < 0) {
  435.             code |= 1;    /* the sign bit */
  436.         }
  437.         Bitio_Write(out, code, nbits);
  438.         first_dct = FALSE;
  439.         } else {
  440.         /*
  441.          * encode using the escape code
  442.          */
  443.         DBG_PRINT(("Escape\n"));
  444.         Bitio_Write(out, 0x1, 6);    /* ESCAPE */
  445.         DBG_PRINT(("Run Length\n"));
  446.         Bitio_Write(out, nzeros, 6);    /* Run-Length */
  447.  
  448.         assert(cur != 0);
  449.  
  450.         /*
  451.              * this shouldn't happen, but the other
  452.              * choice is to bomb out and dump core...
  453.              */
  454.         if (cur < -255) {
  455.             cur = -255;
  456.         } else if (cur > 255) {
  457.             cur = 255;
  458.         }
  459.  
  460.         DBG_PRINT(("Level\n"));
  461.         if (acur < 128) {
  462.             Bitio_Write(out, cur, 8);
  463.         } else {
  464.             if (cur < 0) {
  465.             Bitio_Write(out, 0x8001 + cur + 255, 16);
  466.             } else {
  467.             Bitio_Write(out, cur, 16);
  468.             }
  469.         }
  470.  
  471.         first_dct = FALSE;
  472.         }
  473.         nzeros = 0;
  474.     } else {
  475.         nzeros++;
  476.     }
  477.     }
  478.  
  479.     /* actually, should REALLY return FALSE and not use this! */
  480.     if ( first_dct ) {    /* have to give a first_dct even if all 0's */
  481.     fprintf(stdout, "HUFF called with all-zero coefficients\n");
  482.     fprintf(stdout, "exiting...\n");
  483.     exit(1);
  484.     }
  485.  
  486.     DBG_PRINT(("End of block\n"));
  487.     Bitio_Write(out, 0x2, 2);    /* end of block marker */
  488. }
  489.